// DateEdit object
// Copyright (C) 2005 Outtask, Inc. All Rights Reserved
//<script langauge="javacript">
// REQUIRES popupDiv.js
// REQUIRES bCal.js
// Also requires language files for categories SmallJs and DateTime


if (!window.tryFocus) {
	//copied from functions.js b/c vinnet doesn't include functions.js
	window.tryFocus = function (field) {
	 try {field.focus()}
	 catch (e) {}
	}
}

/*showCal is used in Cliqbook and has been deprecated in favor of otShowCal */
function ShowCal(textboxObj, bCalManagerName, chkValidDates)
{
	if (chkValidDates != null)
		chkValidDates = true;
			
	otShowCal(textboxObj, bCalManagerName, {checkValidDates: chkValidDates, isTravelCal: true});
}

// attach to the edit control's onfocus to create the date popup
function otShowCal(textboxObj, bCalManagerName, options)
{
	if (options == null) options = {};
		
	if (!textboxObj.myPopup)
	{
		if (document.location.host.toLowerCase() != 'app2.outtask.com') {
			if (textboxObj.getAttribute("autocomplete") == null)
				alert('Please add an attribute called autocomplete = "off" to the form field: ' + textboxObj.name);
			if(!textboxObj.id)
				alert('Please add an "ID" attribute to: ' + textboxObj.name);
		}

		if (bCalManagerName) 
			options.popCalManager = bCalManagerName;
		

		var tmpcal = new DateEdit();
		for (opt in options)
		{
			if (options[opt] != null)
				tmpcal[opt] = options[opt];
		}

		//if we are regenerating the input box (via innerhtml), then we have some cleanup work to do
		var oldDiv = $(textboxObj.id + '_bcal')
		if (oldDiv && oldDiv.myPopup) {
			var calPopDiv = oldDiv.myPopup.outerDiv;
			oldDiv.myPopup.unload();
			
			//remove from the DOM the popupDiv (that contains the calendar)
			if (calPopDiv.parentNode){
				calPopDiv.parentNode.removeChild(calPopDiv);
			}
		}

		tmpcal.create(textboxObj.id + "_bcal");
		tmpcal.attachTo(textboxObj.id, 140, 123);
		if (tmpcal.openOnFocus) tmpcal.show();
	}
}

// Disables, but does not destroy an editor's calendar widget
function otDisableCal(textboxObj) {
	if (textboxObj.myPopup) {
		textboxObj.onblur = null;
		textboxObj.onfocus = null;
		textboxObj.onclick = null;
		textboxObj.onkeyup = null;
		if (textboxObj.imageEl) {
			textboxObj.imageEl.onmouseover = null;
			textboxObj.imageEl.onmouseout = null;
			textboxObj.imageEl.onclick = null;
		}
	}
}

// Enables a disabled calendar widget
function otReEnableCal(textboxObj) {
	if (textboxObj.myPopup) {
		textboxObj.onblur = DateEdit_blur;
		textboxObj.onfocus = DateEdit_focus;
		textboxObj.onclick = DateEdit_click;
		textboxObj.onkeyup = DateEdit_keyup;
		if (textboxObj.imageEl) {
			textboxObj.imageEl.onmouseover = DateEdit_imgin;
			textboxObj.imageEl.onmouseout = DateEdit_imgout;
			textboxObj.imageEl.onclick = DateEdit_imgclick;
		}
	}
}

// ******************
// DateEdit class
// ******************

DateEdit.prototype = new otPopupDiv();
DateEdit.prototype.constructor = DateEdit;

// public - constructor
function DateEdit() {
	// private
	this.edit = null;
	this.disableUpdate = false;
	this.accessibleMode = false;

	// public
	this.image = null;
	this.imageOver = null;
	this.imageAlign = "top";
	this.openOnClick = true;			// whether to open list when you click the control
	this.openOnFocus = true;
	this.updateEditOnCalClickOnly = true; //set to false if you want to update textbox everytime you update month/year.
	this.popCal = null;					// you can access bCal members
	this.popCalManager = null; //used when you have a start date and an end date and want to keep them in sync.
	this.dateFormat = 0;
	if (window['userDatePreference'] != null)
		this.dateFormat = userDatePreference;
	this.checkValidDates = false;
	this.checkNotEmpty = true;			// whether to check that the field isn't empty
	this.validateOnBlur = false;		// if enabled, highly annoying. you should call dateEdit.validate() yourself instead.
	this.isTravelCal = false;			// a travel cal has valid dates from yesterday to a year from now.
	
	this.calValidStart = new Date(1900, 0, 1, 0, 0, 0, 0);
	this.calValidEnd = new Date(2079, 11, 31, 23, 59, 59, 0);
	
	this.isStrictDocType = (window['otUseStrict'] ? window['otUseStrict'] : false);
}

// Date formats
DateEdit.prototype.dateFormatChoices = [	// values below are added to our pages by the page template; you can use them
"mm/dd/yyyy",	// OT_DateFormat_MDY_slash = 0
"mm.dd.yyyy",	// OT_DateFormat_MDY_dot = 1
"mm-dd-yyyy",	// OT_DateFormat_MDY_hyphen = 2
"dd/mm/yyyy",	// OT_DateFormat_DMY_slash = 3
"dd.mm.yyyy",	// OT_DateFormat_DMY_dot = 4
"dd-mm-yyyy",	// OT_DateFormat_DMY_hyphen = 5
"yyyy/mm/dd",	// OT_DateFormat_YMD_slash = 6
"yyyy.mm.dd",	// OT_DateFormat_YMD_dot = 7
"yyyy-mm-dd"	// OT_DateFormat_YMD_hyphen = 8
];

// private - used to clear out any circular refs
DateEdit.prototype.unload = function() {
	this.unloadDateEdit();
	this.unloadPopupDiv();
}

// private
DateEdit.prototype.unloadDateEdit = function() {
	if (this.edit != null)
		this.edit.myPopup = null;
	if (this.imageEl != null)
		this.imageEl.myPopup = null;
	this.edit = null;
	// public
	this.image = null;
	this.imageOver = null;
	if (this.popCal) {
		this.popCal.myPopup = null;
		this.popCal = null;
	}
}

// public - used to validate contents of edit
DateEdit.prototype.validate = function() {
	var txt = this.edit.value;
	if (this.checkNotEmpty && /^\s*$/i.test(txt) == true) {
		alert(OTGetUserMessage("DateTime", "DateEmpty"));
		return false;
	}
	if (txt != "") {
		var dt = this.parseDate(txt);
		if (dt == null) {
			alert(OTFormatUserMessage("DateTime", "ParseError", this.dateFormatChoices[this.dateFormat]));
			return false;
		}
		if (this.checkValidDates)
			return this.popCal.checkValidDate(dt);
	}
	return true;
}

// internal
function DateEdit_blur(ev) {
	// can't just hide -- interferes with mouse click
	var pop = this.myPopup;
	
	//alert(pop);
	if (!this.accessibleMode)
		this.stupidIeTimer = setTimeout(function () {if (pop){pop.hide(); pop.oneditblur();}}, 250);
}

// internal
function DateEdit_focus(ev) {
	if (this.stupidIeTimer != null) {
		clearTimeout(this.stupidIeTimer);
		this.stupidIeTimer = null;
	}
	if (this.myPopup.openOnFocus)
		this.myPopup.clickHandler(ev);
	this.myPopup.oneditfocus(ev);
}

// private - give subclass easy access to blur/focus
DateEdit.prototype.oneditblur = function(ev) {
	if (this.validateOnBlur && this.validate() != true) {
		this.edit.select();
		tryFocus(this.edit);
	}
	else {
		if (this.edit && this.edit.onchange)
			this.edit.onchange();
	}
}

// private - give subclass easy access to blur/focus
DateEdit.prototype.oneditfocus = function(ev) {
}

// internal
function DateEdit_click(ev) {
	if (this.myPopup.openOnClick)
		this.myPopup.clickHandler(ev);
}

// internal
DateEdit.prototype.clickHandler = function(ev) {
	if (!this.isVisible()) {
		this.edit.select();
		this.show();
	}
	tryFocus(this.edit);
	//uncomment this if you need to debug the contents of the bcal
	/*
		if (!document.getElementById("acxxx"))
		{
			var te = document.createElement("textarea");
			te.id = "acxxx";
			te.style.width="100%";
			te.style.height="300px";
			te.style.zIndex=99999;
			document.body.appendChild(te);
		}
	
		document.getElementById("acxxx").value = this.popCal.container.innerHTML;
	*/
}

// internal
function DateEdit_divclick(ev) {
	if (window.event)
		ev = window.event;
	var div = ev.target;
	if (div == null)
		div = ev.srcElement;
	var This = div.parentNode.myPopup;
	while (This == null && div.parentNode != null) {
		div = div.parentNode;
		if (div && div.parentNode) This = div.parentNode.myPopup;
	}
	if (This && This.edit) {
		tryFocus(This.edit);
	}
}


function DateEdit_mousedown(ev) {
	if (window.event)
		ev = window.event;
	var div = ev.target;
	if (div == null)
		div = ev.srcElement;
	var This = div.parentNode.myPopup;
	while (This == null && div.parentNode != null) {
		div = div.parentNode;
		if (div && div.parentNode) This = div.parentNode.myPopup;
	}
	if (This && This.edit)
	{
		if (this.mouseDownInterval)
			window.clearInterval(this.mouseDownInterval);
		this.mouseDownInterval = window.setInterval(function() {
			tryFocus(This.edit)
		}, 100);
	}
}

// internal - deal with IE scrollbar getting focus
function DateEdit_sbfocus(ev) {
	if (window.event) {
		window.event.cancelBubble = true;
		tryFocus(this.myPopup.edit);
	}
}

// public - attach to edit control
DateEdit.prototype.attachTo = function(theEdit, width, height) {
	if (typeof(theEdit) == "string")
		theEdit = document.getElementById(theEdit);
	this.positionBelow(theEdit, width);
	if (height == null)
		this.setHeight(Math.ceil(this.parseSize(this.div.offsetWidth) * 0.8) + "px");
	else
		this.setHeight(height);
	theEdit.myPopup = this;
	theEdit.onblur = DateEdit_blur;
	theEdit.onfocus = DateEdit_focus;
	theEdit.onclick = DateEdit_click;
	theEdit.onkeyup = DateEdit_keyup;
	theEdit.setAttribute("AUTOCOMPLETE", "OFF");
	this.edit = theEdit;
	this.div.onfocus = DateEdit_sbfocus;
	this.div.onclick = DateEdit_divclick;
	//this.div.onmousedown = DateEdit_mousedown;
	//this.div.onmouseup = function () {if (this.mouseDownInterval) window.clearInterval(this.mouseDownInterval)}
	if (this.image != null && this.edit.parentNode != null) {
		if (this.imageEl == null) {
			var tempImg = document.createElement('img');
			tempImg.setAttribute('id', 'image' + this.identifier);
			tempImg.setAttribute('src', this.image);
			tempImg.style.border = '0px';
			tempImg.style.verticalAlign = this.imageAlign;
			if (this.edit.nextSibling != null)
				this.imageEl = this.edit.parentNode.insertBefore(tempImg, this.edit.nextSibling);
			else
				this.imageEl = this.edit.parentNode.appentChild(tempImg);
		}
		if (this.imageOver != null) {
			this.imageEl.onmouseover = DateEdit_imgin;
			this.imageEl.onmouseout = DateEdit_imgout;
		}
		this.imageEl.onclick = DateEdit_imgclick;
		this.imageEl.myPopup = this;
		// do this again to take into account image width
		if (width == null) {
			this.positionBelow(this.edit, this.parseSize(this.div.offsetWidth) + this.parseSize(this.imageEl.offsetWidth));
			// null height depends on width
			if (height == null)
				this.setHeight(Math.ceil((this.parseSize(this.div.offsetWidth) + this.parseSize(this.imageEl.offsetWidth)) * 0.8) + "px");
		}
	}
	this.addbCal();
}

// private - parse date text
DateEdit.prototype.parseDate = function(txt) {
	var result = null;
	var s = this.getDateFormat();
	var order = s.replace(/[^mdy]/gi, "").replace(/m+/gi, "m").replace(/d+/gi, "d").replace(/y+/gi, "y");
	s = s.replace(/\./gi, "\\.");
	s = s.replace(/\//gi, "\\/");
	s = s.replace(/\-/gi, "\\-");
	s = s.replace(/y+/gi, "([0-9]+)");
	s = s.replace(/m+/gi, "([0-9]+)");
	s = s.replace(/d+/gi, "([0-9]+)");
	var r = new RegExp("^\s*" + s + "\s*$", "i");
	if (r.test(txt)) {
		var month = 0;
		var day = 0;
		var year = 0;
		var vals = txt.replace(r, "$1,$2,$3").split(",");
		for (var i = 0; i < 3; i++) {
			switch (order.substring(i, i + 1)) {
				case "m":
					month = parseInt(vals[i], 10);
					break;
				case "d":
					day = parseInt(vals[i], 10);
					break;
				case "y":
					year = parseInt(vals[i], 10);
					break;
			}
		}
		if (day >= 0 && month >= 1 && year >= 1900 && day <= 31 && month <= 12 && year <= 2079) {
			result = new Date(year, month - 1, day);
			if (isNaN(result) || result == null)
				result = null;
		}
	}
	return result;
}

// private - format date
DateEdit.prototype.formatDate = function(dt) {
	var s = this.getDateFormat();
	var mo = dt.getMonth() + 1;
	var da = dt.getDate();
	var yr = dt.getFullYear();
	s = s.replace(/yyyy/i, yr);
	s = s.replace(/yy/i, yr.toString().substring(2));
	s = s.replace(/mm/i, (mo < 10 ? '0' + mo : mo));
	s = s.replace(/m/i, mo);
	s = s.replace(/dd/i, (da < 10 ? '0' + da : da));
	s = s.replace(/d/i, da);
	return s;
}

// private - get date format
DateEdit.prototype.getDateFormat = function() {
	var s;
	if (typeof(this.dateFormat) == "number")
		s = this.dateFormatChoices[this.dateFormat];
	else
		s = this.dateFormat.toString();
	return s;
}

// private - override to set date
DateEdit.prototype.onshow = function() {
	var dt = this.parseDate(this.edit.value);
	if (dt == null)
		dt = new Date();
	this.popCal.setMonth(dt.getMonth() + 1);
	this.popCal.setYear(dt.getFullYear());
	this.popCal.selectedDate = dt;
	this.popCal.setCurrentTextBox(this.edit);
	this.popCal.drawCal();
	
	var t = this.div.childNodes[0]; //this will be the outer table
	if (t && t.offsetHeight && t.offsetWidth)
	{
		this.setWidth(t.offsetWidth);
		this.resetHeight();
	}
	
}

// private
DateEdit.prototype.addbCal = function() {

	var popCal = new bCal();
	//popCal.setMonth(this.calValidStart.getMonth() + 1);
	//popCal.setYear(this.calValidStart.getFullYear());
	popCal.container = this.div;
	popCal.calName = "bCal" + this.identifier;
	// stupid hack because of how bCal works.
	//eval("window.bCal" + this.identifier + " = popCal;");
	window['bCal' + this.identifier] = popCal;
	popCal.tLink = "DateEdit_handleDate('" + this.identifier + "', cal_year, cal_month, cal_day, 'tLink')";
	popCal.dLink = "DateEdit_handleDate('" + this.identifier + "', cal_year, cal_month, cal_day, 'dLink')";
	popCal.keyUpLink = "DateEdit_keyUpExt('" + this.identifier + "', event)";
	popCal.keyDnLink = "return DateEdit_keyDnExt('" + this.identifier + "', event)";
	popCal.drawTopBar = false;
	popCal.drawControls = true;
	popCal.tableCellPadding = "0";
	popCal.tableCellSpacing = "0";
	popCal.tableLeftMargin = "0px";	
	popCal.calBG = "white";
	popCal.redrawOnClick = true;
	popCal.setDateRangeOnClick = true;
	popCal.setCalManager(this.popCalManager);
	popCal.calBorder = "none";
	popCal.calPadding = "0px";


	if (this.isTravelCal) {
		this.calValidStart = new Date();
		this.calValidStart.setHours(0, 0, 0, 0);	
		this.calValidEnd = new Date(this.calValidStart.getFullYear() + 1, this.calValidStart.getMonth(), 1);
		this.calValidEnd.setHours(23, 59, 59, 0);
	}

	popCal.validStart = this.calValidStart;
	popCal.validEnd = this.calValidEnd;

	popCal.linkOutOfRangeDates = false
	popCal.dHeadFontSize = "8";
	popCal.dFontSize = "9";
	

	var b = 0;
	var b2 = 0;
	if (!document.all || this.isStrictDocType) {
		b = this.parseSize(this.div.style.borderLeftWidth) + this.parseSize(this.div.style.borderRightWidth) + this.parseSize(this.div.style.paddingLeft) + this.parseSize(this.div.style.paddingRight);
		b2 = this.parseSize(this.div.style.borderTopWidth) + this.parseSize(this.div.style.borderBottomWidth) + this.parseSize(this.div.style.paddingTop) + this.parseSize(this.div.style.paddingBottom);
	}

	popCal.CalWidth = (this.parseSize(this.div.offsetWidth) - b) + "px";
	popCal.CalHeight = (this.parseSize(this.div.offsetHeight) - b2) + "px";

	// Handle post-drawing stuff
	popCal.myPopup = this;
	popCal.ondrawcal = function() {
	
		if (!this.myPopup.updateEditOnCalClickOnly && !this.myPopup.disableUpdate) {
			var dt = this.myPopup.parseDate(this.myPopup.edit.value);
			if (dt == null)
				dt = new Date();
			var lastDay = this.lastDay();
			if (dt.getDate() > lastDay)
				dt.setDate(lastDay);
			dt.setMonth(this.calMonth - 1);
			dt.setYear(this.calYear);
			this.myPopup.edit.value = this.myPopup.formatDate(dt);
		}
		
		tryFocus(this.myPopup.edit);
	}

	// don't need to draw until we show it
	// popCal.drawCal();

	this.popCal = popCal;
}

function DateEdit_handleDate(popCal, yr, mo, da, t) {
	var pop = document.getElementById(popCal).myPopup;
	var dt = new Date(yr, mo - 1, da);
	pop.edit.value = pop.formatDate(dt);
	pop.edit.stupidIeTimer = setTimeout(function() {if (pop && pop.hide) {pop.hide();pop.oneditblur();}}, 250);
}

function DateEdit_imgin(ev) {
	if (this.myPopup.imageEl != null)
		this.myPopup.imageEl.src = this.myPopup.imageOver;
}

function DateEdit_imgout(ev) {
	if (this.myPopup.imageEl != null)
		this.myPopup.imageEl.src = this.myPopup.image;
}

function DateEdit_imgclick(ev) {
	if (this.myPopup.isVisible()) {
		this.myPopup.hide();
		tryFocus(this.myPopup.edit);
	}
	else
		this.myPopup.clickHandler(ev);
}

function DateEdit_keyUpExt(popCal, ev) {
	var parent = document.getElementById(popCal).myPopup.edit;
	return DateEdit_keyupCommon(parent, ev);
}

function DateEdit_keyDnExt(popCal, ev) {
	var parent = document.getElementById(popCal).myPopup.edit;
	
	var keyCode;
	if (window.event)
		keyCode = window.event.keyCode;
	else if (ev)
		keyCode = ev.which;
		
	if (keyCode == 33 || // pgdn
		keyCode == 34 || // pgup
		keyCode == 38 || // up
		keyCode == 40)	// down
	{
		// consume event so the page will not scroll in accessible mode
		var ev2 = ev || window.event;  
	
		if (typeof ev2.stopPropagation != "undefined") {
			ev2.stopPropagation();
		} else {
			ev2.cancelBubble = true;
		}
		return false;
	}
	return true;
}

// internal
function DateEdit_keyup(ev) {
	return DateEdit_keyupCommon(this, ev);
}

function DateEdit_keyupCommon(parent, ev) {	
	var keyCode;
	var isCtrl;
	if (window.event)
		keyCode = window.event.keyCode;
	else if (ev)
		keyCode = ev.which;
		
	var ev2 = ev || window.event;  

	switch (keyCode) {
		case 65:	// A 
		case 77:	// M
			if(ev2.altKey){ // Alt-A or Alt-M (enter accessible mode)  
				parent.accessibleMode = true;
			if (parent.myPopup.popCal.selectedDate)
				parent.myPopup.popCal.accessibleSelectedDate = parent.myPopup.popCal.selectedDate;
			else
					parent.myPopup.popCal.accessibleSelectedDate = new Date();
				parent.myPopup.popCal.drawCal();	
				document.getElementById('bCal' + parent.myPopup.identifier + "_AccessibleSelectedDay").focus();
		}
		return;
		case 38:	// up
			if (parent.accessibleMode)
			{
				parent.myPopup.popCal.accessibleAddDays(-7, 0);
				parent.myPopup.popCal.drawCal();
				document.getElementById('bCal' + parent.myPopup.identifier + "_AccessibleSelectedDay").focus();

			}
			break;
		case 40:	// down
			if (parent.accessibleMode)
			{
				parent.myPopup.popCal.accessibleAddDays(7, 0);
				parent.myPopup.popCal.drawCal();
				document.getElementById('bCal' + parent.myPopup.identifier + "_AccessibleSelectedDay").focus();
			}
			else if (!parent.myPopup.isVisible())
				parent.myPopup.show();			
			break;
		case 33:	// pgup
			if (parent.accessibleMode)
			{
				parent.myPopup.popCal.accessibleAddDays(0, -1);
				parent.myPopup.popCal.drawCal();
				document.getElementById('bCal' + parent.myPopup.identifier + "_AccessibleSelectedDay").focus();
			}
			else if (parent.myPopup.isVisible()) {
				changeMonth(parent.myPopup.popCal, -1);
			}
			break;
		case 34:	// pgdn
			if (parent.accessibleMode)
			{
				parent.myPopup.popCal.accessibleAddDays(0, 1);
				parent.myPopup.popCal.drawCal();
				document.getElementById('bCal' + parent.myPopup.identifier + "_AccessibleSelectedDay").focus();
			}
			else if (parent.myPopup.isVisible()) {
				changeMonth(parent.myPopup.popCal, 1);
			}
			break;
		case 27:	// esc
			parent.accessibleMode = false;
			parent.myPopup.accessibleSelectedDate = null;
			parent.myPopup.popCal.drawCal(); // to redraw without accessible selection
			parent.myPopup.hide();
			return;
			
		case 37:	// left
			if (parent.accessibleMode)
			{
				parent.myPopup.popCal.accessibleAddDays(-1, 0);				
				parent.myPopup.popCal.drawCal();
				document.getElementById('bCal' + parent.myPopup.identifier + "_AccessibleSelectedDay").focus();
			}
			break;
		case 39:	// right
			if (parent.accessibleMode)
			{
				parent.myPopup.popCal.accessibleAddDays(1, 0);
				parent.myPopup.popCal.drawCal();
				document.getElementById('bCal' + parent.myPopup.identifier + "_AccessibleSelectedDay").focus();				
			}
			break;
		case 13:	// cr
			parent.accessibleMode = false;
			parent.myPopup.popCal.accessibleSelectedDate = null;
			parent.myPopup.popCal.drawCal();
			parent.myPopup.edit.stupidIeTimer = setTimeout(function() {if (parent.myPopup && parent.myPopup.edit && parent.myPopup.edit.focus) {parent.myPopup.edit.focus();}}, 350);
			return;
		//break;

		case 9:		// tab		
		case 36:	// home
		case 35:	// end
		case 16:	// shift
		case 17:	// ctrl
		case 18:	// alt
		case 20:	// caps-lock
		case 46:	// del
		case 45:	// ins
		default:
			var d = parent.myPopup.parseDate(parent.myPopup.edit.value);
			if (d != null) {
				parent.myPopup.popCal.setMonth(d.getMonth() + 1);
				parent.myPopup.popCal.setYear(d.getFullYear());
				parent.myPopup.popCal.selectedDate = d;
				parent.myPopup.disableUpdate = true;
				parent.myPopup.popCal.drawCal();
				parent.myPopup.disableUpdate = false;
			}
			break;
	}	
}
